#ifndef SHAPEMANIPULATORS_H
#define SHAPEMANIPULATORS_H

#include <QObject>
class CollisionShape;

class ShapeManipulatorControlPoint
{
public:
    enum MovingConstraint {NO_CONSTRAINT, X_AXIS, Y_AXIS};
    ShapeManipulatorControlPoint(int nIndex = -1);

    void setPosition(const QPointF& pos, bool useConstraint = false);
    const QPointF& position() const { return m_pos; }

    int index() const { return m_nIndex; }
    QPainterPath shape(float manipulatorSize) const;

    void setConstraint(MovingConstraint c);
private:
    QPointF m_pos;
    MovingConstraint m_constraint;
    // -1 for Translation, all other values for Shape Modification Control Points
    int m_nIndex;
};

class ShapeManipulator : public QObject
{
    Q_OBJECT
public:
    ShapeManipulator();

    // NOTE: use here transformedMousePos because view can be zoomed
    bool mousePress(const QPointF &transformedMousePos);
    void mouseMove(const QPointF &transformedMousePos);
    void mouseRelease(const QPointF &transformedMousePos);

    void draw(QPainter& painter) const;
protected:
    virtual void setupManipulator() = 0;
    virtual void updateShape() = 0;
    void updateControlPoints(const QPointF& offset);
    QList<ShapeManipulatorControlPoint*> m_controlPoints;
    ShapeManipulatorControlPoint m_translationPoint;
    ShapeManipulatorControlPoint* m_pGrabbedPoint;
    QPointer<CollisionShape> m_shape;
private:
    void drawManipulator(QPainter& painter, const ShapeManipulatorControlPoint& cp) const;
    float m_manipulationRectSize;
    QPointF m_oldMousePos;
public slots:
    void setShape(QPointer<CollisionShape> shape);
};

class CircleShapeManipulator : public ShapeManipulator
{
    Q_OBJECT
public:
    CircleShapeManipulator();
private:
    void setupManipulator();
    void updateShape();
};

class RectShapeManipulator : public ShapeManipulator
{
    Q_OBJECT
public:
    RectShapeManipulator();
private:
    void setupManipulator();
    void updateShape();
};

class PolyShapeManipulator : public ShapeManipulator
{
    Q_OBJECT
public:
    PolyShapeManipulator();
private:
    void setupManipulator();
    void updateShape();
};


class ShapeManipulatorEngine
{
public:
    ShapeManipulatorEngine();

    void setShape(QPointer<CollisionShape> shape);

    void drawManipulator(QPainter& painter);

    bool mousePress(const QPointF& transformedPoint);
    void mouseMove(const QPointF& transformedPoint);
    void mouseRelease(const QPointF& transformedPoint);

    bool manipulationMode() const;
private:
    QPointer<ShapeManipulator> m_manipulator;

    QPointer<ShapeManipulator> m_circleManipulator;
    QPointer<ShapeManipulator> m_rectManipulator;
    QPointer<ShapeManipulator> m_polyManipulator;
};

#endif // SHAPEMANIPULATORS_H
